/*
 * Copyright (c) 2006-2020, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2020-09-25     chenhy       the first version
 */

#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#define RS485_RTS_PIN       GET_PIN(B, 3)
#define RS485_SERIAL_NAME   "uart1"
struct rt_device rs485;
rt_err_t rs485_tx_done(rt_device_t dev, void *buffer);

rt_err_t rs485_init(rt_device_t dev)
{
    rt_err_t result = RT_EOK;
    rt_device_t rs485_serial;

    dev->user_data = NULL;

    rs485_serial = rt_device_find(RS485_SERIAL_NAME);
    if(!rs485_serial)
        return -1;

    dev->user_data = (void *)rs485_serial;

    return result;
}

rt_err_t rs485_open(rt_device_t dev, rt_uint16_t oflag)
{
    rt_err_t result = RT_EOK;
    if(!dev->user_data)
        return -1;

    result = rt_device_open((rt_device_t)dev->user_data, oflag);
    if(result != RT_EOK) return -1;

    rt_device_set_tx_complete((rt_device_t)dev->user_data, rs485_tx_done);

    rt_pin_mode(RS485_RTS_PIN, PIN_MODE_OUTPUT);
    rt_pin_write(RS485_RTS_PIN, PIN_LOW);

    return result;
}

rt_err_t rs485_close(rt_device_t dev)
{
    rt_err_t result = RT_EOK;
    if(!dev->user_data)
        return -1;

    result = rt_device_close((rt_device_t)dev->user_data);

    return result;
}

rt_size_t rs485_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
    return rt_device_read((rt_device_t)dev->user_data, pos, buffer, size);
}

rt_size_t rs485_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
    rt_pin_write(RS485_RTS_PIN, PIN_HIGH);
    return rt_device_write((rt_device_t)dev->user_data, pos, buffer, size);
}

rt_err_t rs485_control(rt_device_t dev, int cmd, void *args)
{
    return rt_device_control((rt_device_t)dev->user_data, cmd, args);
}

rt_err_t rs485_tx_done(rt_device_t dev, void *buffer)
{
    rt_pin_write(RS485_RTS_PIN, PIN_LOW);
    return RT_EOK;
}

int rs485_register(void)
{
    rs485.type        = RT_Device_Class_Char;
    rs485.rx_indicate = RT_NULL;
    rs485.tx_complete = RT_NULL;
    rs485.init        = rs485_init;
    rs485.open        = rs485_open;
    rs485.close       = rs485_close;
    rs485.read        = rs485_read;
    rs485.write       = rs485_write;
    rs485.control     = rs485_control;
    rs485.user_data   = NULL;

    rt_device_register(&rs485, "rs485", 0);
    return 0;
}
